home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 41
/
Amiga Format CD41 (1999-06)(Future Publishing)(GB)[!][issue 1999-07].iso
/
-seriously_amiga-
/
programming
/
other
/
gtlayout
/
source
/
ltp_popupclass.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-04-19
|
26KB
|
1,285 lines
/*
** GadTools layout toolkit
**
** Copyright © 1993-1998 by Olaf `Olsen' Barthel
** Freely distributable.
**
** :ts=4
*/
#ifndef _GTLAYOUT_GLOBAL_H
#include "gtlayout_global.h"
#endif
/*****************************************************************************/
#include <intuition/classes.h>
#include <clib/alib_protos.h> /* For Coerce/Do/DoSuperMethod */
/*****************************************************************************/
#include "Assert.h"
/*****************************************************************************/
#ifdef DO_POPUP_KIND /* Support code */
#define PIF_SingleActive (1 << 0)
#define PIF_ArrowUp (1 << 1)
#define PIF_ArrowDown (1 << 2)
STATIC VOID
DrawArrow(
struct RastPort * RPort,
LONG Left,
LONG Top,
LONG ArrowWidth,
LONG ArrowHeight,
LONG Dir)
{
LONG i,Width,Start,Pos;
for(i = 0 ; i < ArrowHeight ; i++)
{
Width = ((ArrowWidth * (i + 1)) / ArrowHeight) & ~1;
if(Width < ArrowWidth)
Width++;
Start = Left + (ArrowWidth - Width) / 2;
if(Dir < 0)
Pos = Top + i;
else
Pos = Top + ArrowHeight - 1 - i;
LTP_DrawLine(RPort,Start,Pos,Start + Width - 1,Pos);
}
}
STATIC VOID
DrawContainer(
struct RastPort * RPort,
LONG Left,
LONG Top,
LONG Width,
LONG Height,
struct GadgetInfo * GadgetInfo,
PopInfo * Info,
UWORD Highlight,
UWORD Disabled)
{
LONG Shine,Shadow,Txt,Fill;
LONG Right;
UWORD * Pens;
Pens = GadgetInfo->gi_DrInfo->dri_Pens;
if(Highlight)
{
Shine = Pens[SHADOWPEN];
Shadow = Pens[SHINEPEN];
Txt = Pens[FILLTEXTPEN];
Fill = Pens[FILLPEN];
}
else
{
Shine = Pens[SHINEPEN];
Shadow = Pens[SHADOWPEN];
Txt = Pens[TEXTPEN];
Fill = Pens[BACKGROUNDPEN];
}
LTP_SetPens(RPort,Fill,0,JAM1);
if(Info->FrameImage != NULL)
{
DrawImageState(RPort,Info->FrameImage,Left,Top,Highlight ? IDS_SELECTED : IDS_NORMAL,GadgetInfo->gi_DrInfo);
}
else
{
LTP_FillBox(RPort,Left + 2,Top + 1,Width - 4,Height - 2);
LTP_RenderBevel(RPort,Pens,Left,Top,Width,Height,Highlight,2);
}
Right = Left + Width - Info->MarkLeft;
LTP_SetAPen(RPort,Shadow);
LTP_DrawLine(RPort,Right,Top + 2,Right,Top + Height - 3);
LTP_SetAPen(RPort,Shine);
LTP_DrawLine(RPort,Right + 1,Top + 2,Right + 1,Top + Height - 3);
SetFont(RPort,Info->Font);
LTP_SetAPen(RPort,Txt);
LTP_DrawAdjustedPicker(RPort,FALSE,Right + 2,Top,Info->PickerWidth,Height,Info->AspectX,Info->AspectY);
LTP_PrintText(RPort,Info->Labels[Info->Active],Info->ActiveLen,Left + 6,Top + Info->LabelTop);
if(Disabled)
LTP_GhostBox(RPort,Left,Top,Width,Height,Pens[SHADOWPEN]);
}
STATIC VOID
DrawOneBox(
PopInfo * Info,
LONG Top,
LONG Index)
{
struct RastPort * RPort;
LONG Len;
LONG Extra;
STRPTR Label;
Label = Info->Labels[Index];
RPort = Info->Window->RPort;
if((Len = strlen(Label)) > Info->MaxLen)
Len = Info->MaxLen;
if(Info->CheckGlyph)
Extra = Info->CheckGlyph->Width + 2;
else
Extra = 0;
LTP_PrintText(RPort,Label,Len,6 + Extra,Top + Info->LineTop);
if(Extra && Index == Info->InitialActive)
LTP_DrawCheckGlyph(RPort,6,Top + Info->LineTop,Info->CheckGlyph,Index == Info->LastLabelDrawn);
}
STATIC VOID
DrawOneGlyph(
PopInfo * Info,
LONG Top,
LONG Dir,
UWORD * Pens)
{
struct RastPort *RPort;
RPort = Info->Window->RPort;
if(Pens != NULL)
{
LTP_SetAPen(RPort,Info->MenuBack);
LTP_FillBox(RPort,4,Top,Info->SingleWidth,Info->SingleHeight);
LTP_SetAPen(RPort,Info->MenuText);
}
DrawArrow(RPort,6,Top + Info->ArrowTop,Info->ArrowWidth,Info->ArrowHeight,Dir);
}
STATIC VOID
BoxRender(
PopInfo * Info,
UWORD * Pens,
LONG Active,
BOOL FullRefresh,
BOOL Highlight,
LONG Dir)
{
struct RastPort *RPort = Info->Window->RPort;
if(FullRefresh)
{
LONG Index,Top;
LONG Width,Height;
LTP_SetPens(RPort,Info->MenuBack,0,JAM1);
Width = Info->Window->Width;
Height = Info->Window->Height;
LTP_FillBox(RPort,2,1,Width - 4,Height - 2);
LTP_SetAPen(RPort,Info->MenuText);
LTP_PolyDraw(RPort,5,
1,1,
1,Height - 2,
0,Height - 2,
0,0,
Width - 1,0);
LTP_PolyDraw(RPort,5,
0,Height - 1,
Width - 1,Height - 1,
Width - 1,1,
Width - 2,1,
Width - 2,Height - 2);
Index = Info->TopMost;
Top = 2;
Height = Info->BoxHeight;
Info->Flags &= ~(PIF_ArrowUp | PIF_ArrowDown);
if(Info->TopMost > 0 && Active != Info->TopMost && Info->BoxLines > 2)
{
Info->Flags |= PIF_ArrowUp;
Index += 1;
Top += Info->SingleHeight;
Height -= Info->SingleHeight;
}
if(Info->TopMost + Info->BoxLines < Info->NumLabels && Active != Info->TopMost + Info->BoxLines - 1 && Info->BoxLines > 2)
{
Info->Flags |= PIF_ArrowDown;
Height -= Info->SingleHeight;
}
Info->LastLabelDrawn = Active; // IMPORTANT: must be set up here to DrawOneBox can find it
for(NULL ; Index < Info->NumLabels && Height > 0 ; Index++, Top += Info->SingleHeight, Height -= Info->SingleHeight)
{
if(Index == Active)
{
LTP_SetAPen(RPort,Info->MenuBackSelect);
LTP_FillBox(RPort,4,Top,Info->SingleWidth,Info->SingleHeight);
LTP_SetAPen(RPort,Info->MenuTextSelect);
DrawOneBox(Info,Top,Index);
LTP_SetAPen(RPort,Info->MenuText);
}
else
{
DrawOneBox(Info,Top,Index);
}
}
if(Info->Flags & PIF_ArrowUp)
DrawOneGlyph(Info,2,-1,NULL);
if(Info->Flags & PIF_ArrowDown)
DrawOneGlyph(Info,2 + (Info->BoxLines - 1) * Info->SingleHeight,1,NULL);
Info->LastDrawn = 2 + (Active - Info->TopMost) * Info->SingleHeight;
}
else
{
if(Info->LastLabelDrawn != -1)
{
LONG Top = Info->LastDrawn,Last = Info->LastLabelDrawn;
Info->LastLabelDrawn = -1;
LTP_SetPens(RPort,Info->MenuBack,0,JAM1);
LTP_FillBox(RPort,4,Top,Info->SingleWidth,Info->SingleHeight);
LTP_SetAPen(RPort,Info->MenuText);
DrawOneBox(Info,Top,Last);
}
Info->LastDrawn = -1;
if(Active >= 0)
{
LONG Top,NewActive;
NewActive = Active - Info->TopMost;
Top = 2 + NewActive * Info->SingleHeight;
if(Top >= 2 && Top < Info->BoxHeight + 2)
{
LONG Pen;
if(Dir != 0)
Highlight = FALSE;
if(Highlight)
{
Pen = Info->MenuBackSelect;
Info->LastDrawn = Top;
Info->LastLabelDrawn = Active;
}
else
{
Pen = Info->MenuBack;
}
LTP_SetPens(RPort,Pen,0,JAM1);
LTP_FillBox(RPort,4,Top,Info->SingleWidth,Info->SingleHeight);
if(Highlight)
Pen = Info->MenuTextSelect;
else
Pen = Info->MenuText;
LTP_SetAPen(RPort,Pen);
if(Dir == 0)
DrawOneBox(Info,Top,Active);
else
DrawOneGlyph(Info,Top,Dir,NULL);
}
}
}
}
STATIC ULONG
InputMethod(
struct IClass * class,
struct Gadget * gadget,
struct gpInput * InputInfo)
{
PopInfo *Info = INST_DATA(class,gadget);
ULONG Result = GMR_MEACTIVE;
BOOL Done = FALSE;
BOOL Redraw = FALSE;
if(InputInfo->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
{
UWORD Code = InputInfo->gpi_IEvent->ie_Code;
if(Code == MENUDOWN)
{
Result = GMR_NOREUSE;
Done = TRUE;
Info->Active = Info->InitialActive;
}
else
{
if(Code == SELECTUP)
{
Done = TRUE;
if(Info->Active < 0)
{
Result = GMR_NOREUSE;
Info->Active = Info->InitialActive;
}
else
{
LONG Len;
Result = GMR_NOREUSE | GMR_VERIFY;
if(Info->Flags & PIF_SingleActive)
{
LONG Width,Height;
LONG x,y;
x = InputInfo->gpi_Mouse.X;
y = InputInfo->gpi_Mouse.Y;
Width = gadget->Width;
Height = gadget->Height;
if(x >= 0 && y >= 0 && x < Width && y < Height)
{
if(InputInfo->gpi_IEvent->ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
Info->Active--;
else
Info->Active++;
if(Info->Active >= Info->NumLabels)
{
Info->Active = 0;
}
else
{
if(Info->Active < 0)
Info->Active = Info->NumLabels - 1;
}
}
else
{
Result = GMR_NOREUSE;
Info->Active = Info->InitialActive;
}
}
Len = strlen(Info->Labels[Info->Active]);
if(Len > Info->MaxLen)
Len = Info->MaxLen;
Info->ActiveLen = Len;
(*InputInfo->gpi_Termination) = Info->Active;
}
}
else
{
if(Info->Flags & PIF_SingleActive)
{
LONG Width,Height;
LONG x,y;
BOOL RefreshIt = FALSE;
x = InputInfo->gpi_Mouse.X;
y = InputInfo->gpi_Mouse.Y;
Width = gadget->Width;
Height = gadget->Height;
if(x < 0 || y < 0 || x >= Width || y >= Height)
{
if(gadget->Flags & GFLG_SELECTED)
RefreshIt = TRUE;
}
else
{
if(!(gadget->Flags & GFLG_SELECTED))
RefreshIt = TRUE;
}
if(RefreshIt)
{
gadget->Flags ^= GFLG_SELECTED;
Redraw = TRUE;
}
}
}
}
if(Done)
{
if(gadget->Flags & GFLG_SELECTED)
{
gadget->Flags &= ~GFLG_SELECTED;
Redraw = TRUE;
}
if(Info->Window != NULL)
{
CloseWindow(Info->Window);
Info->Window = NULL;
}
LTP_DeleteCheckGlyph(Info->CheckGlyph);
Info->CheckGlyph = NULL;
Info->Flags &= ~PIF_SingleActive;
}
}
if(!Done && Info->Window)
{
LONG NewActive = 0;
LONG x,y;
LONG Dir = 0;
LONG From = 0,To = 0; /* Initialize these for the sake of the compiler. */
x = InputInfo->gpi_GInfo->gi_Screen->MouseX - Info->BoxLeft;
y = InputInfo->gpi_GInfo->gi_Screen->MouseY - Info->BoxTop;
if(x < 0 || x >= Info->BoxWidth)
{
NewActive = -1;
}
else
{
LONG Margin;
if(Info->Flags & (PIF_ArrowUp | PIF_ArrowDown))
Margin = Info->SingleHeight;
else
Margin = (Info->SingleHeight + 3) / 4;
// Scroll up?
if(y < Margin)
{
if(y < 0)
{
NewActive = -1;
}
else
{
// Topmost line concealed?
if(Info->TopMost > 0)
{
Info->TopMost--;
From = 2;
To = 2 + Info->BoxHeight - 1;
Dir = -Info->SingleHeight;
}
}
}
else
{
LONG Last;
Last = Info->NumLabels - Info->TopMost;
if(Last < Info->BoxLines)
Last = Last * Info->SingleHeight;
else
Last = Info->BoxHeight;
// Scroll up?
if(y >= Last - Margin)
{
if(y >= Last)
{
NewActive = -1;
}
else
{
// Last line concealed?
if(Info->TopMost + Info->BoxLines < Info->NumLabels)
{
Info->TopMost++;
From = 2;
To = 2 + Info->BoxHeight - 1;
Dir = Info->SingleHeight;
}
}
}
}
if(NewActive != -1)
{
NewActive = Info->TopMost + y / Info->SingleHeight;
if(NewActive < 0)
{
NewActive = 0;
}
else
{
if(NewActive >= Info->NumLabels)
NewActive = Info->NumLabels - 1;
}
}
}
if(NewActive != Info->Active || Dir != 0)
{
LONG Arrow;
UWORD * Pens = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
if(Dir != 0)
{
struct RastPort *RPort = Info->Window->RPort;
Arrow = (NewActive == Info->TopMost) ? -1 : 1;
BoxRender(Info,Pens,-1,FALSE,FALSE,0);
if(Info->Flags & PIF_ArrowUp)
From += Info->SingleHeight;
if(Info->Flags & PIF_ArrowDown)
To -= Info->SingleHeight;
SetBPen(RPort,Pens[BACKGROUNDPEN]);
ScrollRaster(RPort,0,Dir,4,From,4 + Info->BoxWidth - 1,To);
if(Dir < 0)
BoxRender(Info,Pens,Info->TopMost + 1,FALSE,FALSE,0);
else
BoxRender(Info,Pens,Info->TopMost + Info->BoxLines - 2,FALSE,FALSE,0);
if(!Info->TopMost || Info->BoxLines < 3)
{
Info->Flags &= ~PIF_ArrowUp;
Arrow = 0;
}
else
{
if(!(Info->Flags & PIF_ArrowUp))
{
Info->Flags |= PIF_ArrowUp;
DrawOneGlyph(Info,2,-1,Pens);
}
}
if(Info->TopMost + Info->BoxLines >= Info->NumLabels || Info->BoxLines < 3)
{
Info->Flags &= ~PIF_ArrowDown;
Arrow = 0;
}
else
{
if(!(Info->Flags & PIF_ArrowDown))
{
Info->Flags |= PIF_ArrowDown;
DrawOneGlyph(Info,2 + (Info->BoxLines - 1) * Info->SingleHeight,1,Pens);
}
}
}
else
{
Arrow = 0;
}
Info->Active = NewActive;
BoxRender(Info,Pens,NewActive,FALSE,TRUE,Arrow);
}
}
if(Redraw)
{
struct RastPort * RPort;
RPort = ObtainGIRPort(InputInfo->gpi_GInfo);
if(RPort != NULL)
{
DoMethod((Object *)gadget,GM_RENDER,InputInfo->gpi_GInfo,RPort,GREDRAW_UPDATE);
ReleaseGIRPort(RPort);
}
}
return(Result);
}
STATIC VOID
SetMethod(
struct IClass * class,
struct Gadget * gadget,
struct opSet * SetInfo)
{
PopInfo * Info = INST_DATA(class,gadget);
struct TagItem * This;
LONG NewActive;
STRPTR * NewLabels;
UWORD Flags = gadget -> Flags;
BOOL NeedRefresh = FALSE;
LONG LabelCount;
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
DoSuperMethodA(class,(Object *)gadget,(Msg)SetInfo);
if((This = FindTagItem(GA_Disabled,SetInfo->ops_AttrList)) != NULL)
{
if(This -> ti_Data && !(Flags & GFLG_DISABLED) || !This -> ti_Data && (Flags & GFLG_DISABLED))
NeedRefresh = TRUE;
}
NewLabels = (STRPTR *)GetTagData(PIA_Labels,NULL,SetInfo->ops_AttrList);
if(NewLabels != NULL)
{
for(LabelCount = 0 ; NewLabels[LabelCount] != NULL ; LabelCount++)
NULL;
}
else
{
LabelCount = Info->NumLabels;
}
if((This = FindTagItem(PIA_Active,SetInfo->ops_AttrList)) != NULL)
{
NewActive = (LONG)This->ti_Data;
if(NewActive < 0)
{
NewActive = 0;
}
else
{
if(NewActive >= LabelCount)
NewActive = LabelCount - 1;
}
}
else
{
NewActive = -1;
}
if((NewActive != Info->Active && NewActive != -1) || (NewLabels != NULL))
{
if(NewLabels == (STRPTR *)~0)
{
Info->Blocked = TRUE;
}
else
{
struct RastPort *RPort;
Info->Blocked = FALSE;
RPort = ObtainGIRPort(SetInfo->ops_GInfo);
if(RPort != NULL)
{
LONG Len;
STRPTR * Labels;
LONG MaxLen,ActiveLen;
if(NewLabels != NULL)
{
struct TextExtent Extent;
LONG i;
for(i = 0, MaxLen = 0 ; i < LabelCount ; i++)
{
Len = TextFit(RPort,NewLabels[i],strlen(NewLabels[i]),&Extent,NULL,1,Info->MaxWidth,32767);
if(Len > MaxLen)
MaxLen = Len;
}
Labels = NewLabels;
}
else
{
Labels = Info->Labels;
MaxLen = Info->MaxLen;
}
if(NewActive == -1)
NewActive = Info->Active;
if(NewActive >= LabelCount)
NewActive = LabelCount - 1;
Len = strlen(Labels[NewActive]);
if(Len > MaxLen)
Len = MaxLen;
ActiveLen = Len;
Info->Active = NewActive;
Info->ActiveLen = ActiveLen;
if(NewLabels != NULL)
{
Info->Labels = NewLabels;
Info->NumLabels = LabelCount;
Info->MaxLen = MaxLen;
}
NeedRefresh = TRUE;
ReleaseGIRPort(RPort);
}
}
}
if(!(gadget -> Flags & GFLG_DISABLED) && (This = FindTagItem(PIA_Highlight,SetInfo->ops_AttrList)))
{
if(This->ti_Data)
gadget->Flags |= GFLG_SELECTED;
else
gadget->Flags &= ~GFLG_SELECTED;
NeedRefresh = TRUE;
}
if(NeedRefresh)
{
struct RastPort *RPort;
if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
{
DoMethod((Object *)gadget,GM_RENDER,SetInfo->ops_GInfo,RPort,GREDRAW_UPDATE);
ReleaseGIRPort(RPort);
}
}
}
STATIC ULONG
RenderMethod(
struct IClass * class,
struct Gadget * gadget,
struct gpRender * RenderInfo)
{
PopInfo *Info = INST_DATA(class,gadget);
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
DrawContainer(RenderInfo->gpr_RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,RenderInfo->gpr_GInfo,Info,gadget->Flags & GFLG_SELECTED,gadget->Flags & GFLG_DISABLED);
return(TRUE);
}
STATIC VOID
DisposeMethod(
struct IClass * class,
Object * object,
Msg msg)
{
PopInfo *Info = INST_DATA(class,object);
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
if(Info->Font != NULL)
{
CloseFont(Info->Font);
Info->Font = NULL;
}
if(Info->Window != NULL)
{
CloseWindow(Info->Window);
Info->Window = NULL;
}
LTP_DeleteCheckGlyph(Info->CheckGlyph);
Info->CheckGlyph = NULL;
if(Info->FrameImage != NULL)
{
DisposeObject(Info->FrameImage);
Info->FrameImage = NULL;
}
}
STATIC ULONG
NewMethod(
struct IClass * class,
Object * object,
struct opSet * SetInfo)
{
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
object = (Object *)DoSuperMethodA(class,object,(Msg)SetInfo);
if(object != NULL)
{
PopInfo * Info = INST_DATA(class,object);
struct TagItem * Item;
struct TagItem * TagList = SetInfo -> ops_AttrList;
struct TextAttr * Font = NULL;
LONG Width = 0;
LONG Height = 0;
LONG AspectX = 1;
LONG AspectY = 1;
memset(Info,0,sizeof(PopInfo));
while((Item = NextTagItem(&TagList)) != NULL)
{
switch(Item->ti_Tag)
{
case GA_Width:
Width = Item->ti_Data;
break;
case GA_Height:
Height = Item->ti_Data;
break;
case PIA_Labels:
Info->Labels = (STRPTR *)Item->ti_Data;
break;
case PIA_Active:
Info->Active = (LONG)Item->ti_Data;
break;
case PIA_Font:
Font = (struct TextAttr *)Item->ti_Data;
break;
case PIA_CentreActive:
Info->CentreActive = Item->ti_Data;
break;
case PIA_AspectX:
AspectX = Item->ti_Data;
break;
case PIA_AspectY:
AspectY = Item->ti_Data;
break;
}
}
Info->AspectX = AspectX;
Info->AspectY = AspectY;
if(V39)
{
Info->FrameImage = (struct Image *)NewObject(NULL,FRAMEICLASS,
IA_Width, Width,
IA_Height, Height,
IA_FrameType, FRAME_BUTTON,
TAG_DONE);
}
if(Font && Info->Labels != NULL && Info->Labels != (STRPTR *)~0 && Width && Height)
{
while(Info->Labels[Info->NumLabels])
Info->NumLabels++;
if(Info->NumLabels)
{
Info->Font = OpenFont(Font);
if(Info->Font != NULL)
{
struct RastPort RPort;
if(Info->Active < 0)
{
Info->Active = 0;
}
else
{
if(Info->Active >= Info->NumLabels)
Info->Active = Info->NumLabels - 1;
}
InitRastPort(&RPort);
SetFont(&RPort,Info->Font);
Info->PickerWidth = LTP_GetPickerWidth(Font->ta_YSize,AspectX,AspectY);
Info->ArrowWidth = (TextLength(&RPort,"M",1) & ~1) + 1;
Info->ArrowHeight = (2 * RPort.TxHeight) / 3;
Info->ArrowTop = (Height - Info->ArrowHeight) / 2;
Info->MarkWidth = Info->PickerWidth;
Info->MarkLeft = 4 + Info->MarkWidth;
Info->PopLeft = 0;
Info->PopWidth = Width;
Info->LabelTop = (Height - RPort.TxHeight) / 2;
Width -= 6 + Info->MarkWidth + 6;
Height -= 2 + RPort.TxHeight + 2;
if(Width > 0 && Height >= 0)
{
struct TextExtent Extent;
LONG i,Len,MaxLen;
for(i = MaxLen = 0 ; i < Info->NumLabels ; i++)
{
Len = TextFit(&RPort,Info->Labels[i],strlen(Info->Labels[i]),&Extent,NULL,1,Width,32767);
if(Len > MaxLen)
MaxLen = Len;
}
if(MaxLen)
{
Len = strlen(Info->Labels[Info->Active]);
if(Len > MaxLen)
Len = MaxLen;
Info->ActiveLen = Len;
Info->MaxLen = MaxLen;
Info->MaxWidth = Width;
return((ULONG)object);
}
}
CloseFont(Info->Font);
Info->Font = NULL;
}
}
}
CoerceMethod(class,object,OM_DISPOSE);
}
return(0);
}
STATIC ULONG
ActiveMethod(
struct IClass * class,
struct Gadget * gadget,
struct gpInput * InputInfo)
{
PopInfo * Info = INST_DATA(class,gadget);
struct RastPort * RPort;
struct GadgetInfo * GInfo;
if(Info->Blocked || (gadget->Flags & GFLG_DISABLED))
return(GMR_NOREUSE);
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
GInfo = InputInfo->gpi_GInfo;
RPort = ObtainGIRPort(GInfo);
if(RPort != NULL)
{
LONG Left,Top;
Left = gadget->LeftEdge;
Top = gadget->TopEdge;
Info->Window = NULL;
if(Info->NumLabels > 2 && InputInfo->gpi_Mouse.X < gadget->Width - Info->MarkLeft && V39)
{
LONG SingleHeight,ScreenHeight,Width,Height;
Info->Flags &= ~PIF_SingleActive;
Info->Window = NULL;
SetFont(RPort,Info->Font);
SingleHeight = gadget->Height;
ScreenHeight = GInfo->gi_Screen->Height;
Info->LineTop = (SingleHeight - RPort->TxHeight) / 2;
Width = Info->PopWidth;
Height = 2 + SingleHeight * Info->NumLabels + 2;
while(Height > SingleHeight && Height > ScreenHeight)
Height -= SingleHeight;
if(Height > SingleHeight)
{
struct DrawInfo *DrawInfo;
UWORD *Pens;
LONG LeftEdge,TopEdge;
LONG TopMost;
LONG Plus;
LeftEdge = GInfo->gi_Window->LeftEdge + Left + Info->PopLeft;
TopEdge = GInfo->gi_Window->TopEdge + Top + Info->LabelTop - (2 + Info->LineTop + Info->Active * SingleHeight);
TopMost = 0;
if(Info->CentreActive)
Plus = 1;
else
Plus = 0;
while(TopEdge < 0 && TopMost < Info->NumLabels)
{
TopEdge += SingleHeight;
TopMost += Plus;
}
DrawInfo = GInfo->gi_DrInfo;
Pens = DrawInfo->dri_Pens;
if(V39)
{
Info->MenuText = Pens[BARDETAILPEN];
Info->MenuBack = Pens[BARBLOCKPEN];
}
else
{
Info->MenuText = Pens[DETAILPEN];
Info->MenuBack = Pens[BLOCKPEN];
}
Info->CheckGlyph = LTP_CreateCheckGlyph((RPort->TxHeight * DrawInfo->dri_Resolution.Y) / DrawInfo->dri_Resolution.X,RPort->TxHeight,GInfo->gi_Window->RPort->BitMap,Info->MenuText,Info->MenuBack);
if((Info->CheckGlyph != NULL) && (TopEdge >= 0) && (TopMost < Info->NumLabels))
{
while((Height > SingleHeight) && (TopEdge + Height > ScreenHeight))
Height -= SingleHeight;
if((Height > SingleHeight) && (TopEdge + Height <= ScreenHeight))
{
ReleaseGIRPort(RPort);
Info->Window = OpenWindowTags(NULL,
WA_Left, LeftEdge,
WA_Top, TopEdge,
WA_Width, Width,
WA_Height, Height,
WA_SimpleRefresh, TRUE,
WA_NoCareRefresh, TRUE,
WA_AutoAdjust, FALSE,
WA_CustomScreen, GInfo->gi_Screen,
WA_Borderless, TRUE,
V39 ? WA_BackFill : TAG_IGNORE,LAYERS_NOBACKFILL,
TAG_DONE);
if(Info->Window != NULL)
{
Info->TopMost = TopMost;
Info->BoxLeft = LeftEdge + 4;
Info->BoxTop = TopEdge + 2;
Info->BoxWidth = Width - 8;
Info->BoxHeight = Height - 4;
Info->BoxLines = Info->BoxHeight / SingleHeight;
Info->SingleWidth = Width - 8;
Info->SingleHeight = SingleHeight;
if(V39)
{
STATIC const BYTE RenderPens[] =
{
BACKGROUNDPEN,
FILLPEN,
TEXTPEN,
FILLTEXTPEN,
SHADOWPEN,
SHINEPEN,
BARDETAILPEN,
BARBLOCKPEN
-1
};
LONG i,Pen,Max = 0;
Info->MenuTextSelect = Pens[BARBLOCKPEN];
Info->MenuBackSelect = Pens[BARDETAILPEN];
for(i = 0 ; RenderPens[i] != -1 ; i++)
{
if((Pen = Pens[RenderPens[i]]) > Max)
Max = Pen;
}
SetMaxPen(Info->Window->RPort,Max);
}
else
{
Info->MenuTextSelect = ~Pens[DETAILPEN];
Info->MenuBackSelect = ~Pens[BLOCKPEN];
}
SetFont(Info->Window->RPort,Info->Font);
}
RPort = ObtainGIRPort(GInfo);
if(RPort == NULL)
{
if(Info->Window != NULL)
{
CloseWindow(Info->Window);
Info->Window = NULL;
}
}
}
}
}
}
if(Info->Window == NULL)
{
LTP_DeleteCheckGlyph(Info->CheckGlyph);
Info->CheckGlyph = NULL;
Info->Flags |= PIF_SingleActive;
}
if(((Info->Flags & PIF_SingleActive) || (Info->Window != NULL)) && (RPort != NULL))
{
Info->InitialActive = Info->Active;
gadget->Flags |= GFLG_SELECTED;
if(!Info->CheckGlyph)
DoMethod((Object *)gadget,GM_RENDER,GInfo,RPort,GREDRAW_UPDATE);
ReleaseGIRPort(RPort);
if(Info->Window)
BoxRender(Info,GInfo->gi_DrInfo->dri_Pens,Info->Active,TRUE,TRUE,0);
return(GMR_MEACTIVE);
}
if(RPort != NULL)
ReleaseGIRPort(RPort);
}
return(GMR_NOREUSE);
}
STATIC ULONG
InactiveMethod(
struct IClass * class,
struct Gadget * gadget,
struct gpGoInactive * InactiveInfo)
{
PopInfo *Info = INST_DATA(class,gadget);
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
gadget->Flags &= ~GFLG_SELECTED;
if((Info->Window != NULL) || (Info->Flags & PIF_SingleActive))
{
struct RastPort *RPort;
if(Info->Window)
{
CloseWindow(Info->Window);
Info->Window = NULL;
}
if(!Info->CheckGlyph)
{
if(RPort = ObtainGIRPort(InactiveInfo->gpgi_GInfo))
{
DoMethod((Object *)gadget,GM_RENDER,InactiveInfo->gpgi_GInfo,RPort,GREDRAW_UPDATE);
ReleaseGIRPort(RPort);
}
}
LTP_DeleteCheckGlyph(Info->CheckGlyph);
Info->CheckGlyph = NULL;
Info->Flags &= ~PIF_SingleActive;
}
return(0);
}
ULONG SAVE_DS ASM
LTP_PopupClassDispatcher(
REG(a0) struct IClass * class,
REG(a2) Object * object,
REG(a1) Msg msg)
{
switch(msg->MethodID)
{
case OM_NEW:
return(NewMethod(class,object,(struct opSet *)msg));
case OM_UPDATE:
case OM_SET:
SetMethod(class,(struct Gadget *)object,(struct opSet *)msg);
break;
case GM_RENDER:
return(RenderMethod(class,(struct Gadget *)object,(struct gpRender *)msg));
case GM_HITTEST:
return(GMR_GADGETHIT);
case GM_GOINACTIVE:
return(InactiveMethod(class,(struct Gadget *)object,(struct gpGoInactive *)msg));
case GM_GOACTIVE:
return(ActiveMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
case GM_HANDLEINPUT:
return(InputMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
case OM_DISPOSE:
DisposeMethod(class,object,msg);
// Falls down to the default case...
}
return(DoSuperMethodA(class,object,msg));
}
#endif /* DO_POPUP_KIND */